import utils from 'axios/unsafe/utils.js';
import settle from 'axios/unsafe/core/settle.js';
import cookies from 'axios/unsafe/helpers/cookies.js';
import buildURL from 'axios/unsafe/helpers/buildURL.js';
import buildFullPath from 'axios/unsafe/core/buildFullPath.js';
import parseHeaders from 'axios/unsafe/helpers/parseHeaders.js';
import isURLSameOrigin from 'axios/unsafe/helpers/isURLSameOrigin.js';
import transitionalDefaults from 'axios/unsafe/defaults/transitional.js';
import AxiosError from 'axios/unsafe/core/AxiosError.js';
import CanceledError from 'axios/unsafe/cancel/CanceledError.js';
import parseProtocol from 'axios/unsafe/helpers/parseProtocol.js';
import platform from 'axios/unsafe/platform/index.js';
import formDataEncode from 'formdata-encode';

export default function uniAdapter(config) {
    return new Promise(async function dispatchUniRequest(resolve, reject) {
        var requestData = config.data;
        var requestHeaders = config.headers;
        var responseType = config.responseType;
        var onCanceled;
        function done() {
            if (config.cancelToken) {
                config.cancelToken.unsubscribe(onCanceled);
            }

            if (config.signal) {
                config.signal.removeEventListener('abort', onCanceled);
            }
        }

        // if (utils.isFormData(requestData) && utils.isStandardBrowserEnv()) {
        //     delete requestHeaders['Content-Type']; // Let the browser set it
        // }
        if (utils.isFormData(requestData)) {
            const blob = formDataEncode(requestData);
            requestHeaders['Content-Type'] = blob.type;
            requestData = await blob.arrayBuffer();
        }

        // HTTP basic authentication
        if (config.auth) {
            var username = config.auth.username || '';
            var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
            requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
        }

        var fullPath = buildFullPath(config.baseURL, config.url);

        // request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);

        // Set the request timeout in MS
        // request.timeout = config.timeout;

        function success({ data, statusCode, header: responseHeaders, cookies }) {
            if (!requestTask) {
                return;
            }
            // Prepare the response
            // var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
            // var responseData = !responseType || responseType === 'text' || responseType === 'json' ?
            //     request.responseText : request.response;
            // console.log("statusCode", statusCode)
            console.log("success", arguments)
            var response = {
                data: data,
                status: statusCode,
                statusText: '',
                headers: responseHeaders,
                config: config,
                request: requestTask
            };

            settle(function _resolve(value) {
                resolve(value);
                done();
            }, function _reject(err) {
                reject(err);
                done();
            }, response);

            // Clean up request
            requestTask = null;
        }

        // if ('onloadend' in request) {
        //     // Use onloadend if available
        //     request.onloadend = onloadend;
        // } else {
        //     // Listen for ready state to emulate onloadend
        //     request.onreadystatechange = function handleLoad() {
        //         if (!request || request.readyState !== 4) {
        //             return;
        //         }

        //         // The request errored out and we didn't get a response, this will be
        //         // handled by onerror instead
        //         // With one exception: request that using file: protocol, most browsers
        //         // will return status as 0 even though it's a successful request
        //         if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
        //             return;
        //         }
        //         // readystate handler is calling before onerror or ontimeout handlers,
        //         // so we should call onloadend on the next 'tick'
        //         setTimeout(onloadend);
        //     };
        // }

        // Handle browser request cancellation (as opposed to a manual cancellation)
        function handleAbort() {
            if (!requestTask) {
                return;
            }

            reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, requestTask));

            // Clean up request
            requestTask = null;
        };

        // Handle low level network errors
        function handleError() {
            // Real errors are hidden from us by the browser
            // onerror should only fire if it's a network error
            reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, requestTask));

            // Clean up request
            requestTask = null;
        };

        // Handle timeout
        function handleTimeout() {
            var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
            var transitional = config.transitional || transitionalDefaults;
            if (config.timeoutErrorMessage) {
                timeoutErrorMessage = config.timeoutErrorMessage;
            }
            reject(new AxiosError(
                timeoutErrorMessage,
                transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
                config,
                requestTask));

            // Clean up request
            requestTask = null;
        };

        function fail({ errMsg }) {
            console.log(errMsg, arguments)
            if ((errMsg + "").toLowerCase().includes("abort")) {
                handleAbort();
            } else if ((errMsg + "").toLowerCase().includes("timeout")) {
                handleTimeout();
            } else {
                handleError();
            }
        }

        // Add xsrf header
        // This is only done if running in a standard browser environment.
        // Specifically not if we're in a web worker, or react-native.
        // if (utils.isStandardBrowserEnv()) {
        //     // Add xsrf header
        //     var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?
        //         cookies.read(config.xsrfCookieName) :
        //         undefined;

        //     if (xsrfValue) {
        //         requestHeaders[config.xsrfHeaderName] = xsrfValue;
        //     }
        // }

        // Add headers to the request
        // if ('setRequestHeader' in request) {
        //     utils.forEach(requestHeaders, function setRequestHeader(val, key) {
        //         if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
        //             // Remove Content-Type if data is undefined
        //             delete requestHeaders[key];
        //         } else {
        //             // Otherwise add header to the request
        //             request.setRequestHeader(key, val);
        //         }
        //     });
        // }

        // Add withCredentials to request if needed
        // if (!utils.isUndefined(config.withCredentials)) {
        //     request.withCredentials = !!config.withCredentials;
        // }

        // Add responseType to request if needed
        // if (responseType && responseType !== 'json') {
        //     request.responseType = config.responseType;
        // }

        // Handle progress if needed
        // if (typeof config.onDownloadProgress === 'function') {
        //     request.addEventListener('progress', config.onDownloadProgress);
        // }

        // // Not all browsers support upload events
        // if (typeof config.onUploadProgress === 'function' && request.upload) {
        //     request.upload.addEventListener('progress', config.onUploadProgress);
        // }

        var enableChunked = false;

        utils.forEach(requestHeaders, function setRequestHeader(val, key) {
            if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
                delete requestHeaders[key];
            } else if (typeof requestData === 'undefined' && key.toLowerCase() === 'transfer-encoding') {
                enableChunked = (requestHeaders[key] + "").toLowerCase() === "chunked";
            }

        });
        if (!requestData) {
            requestData = null;
        }

        var protocol = parseProtocol(fullPath);

        if (protocol && platform.protocols.indexOf(protocol) === -1) {
            reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config));
            return;
        }


        // Send the request
        // request.send(requestData);
        // console.log({
        //     url: buildURL(fullPath, config.params, config.paramsSerializer),
        //     data: requestData,
        //     method: config.method.toUpperCase(),
        //     header: requestHeaders.toJSON(),
        //     timeout: config.timeout < 1 ? undefined : config.timeout,
        //     dataType: responseType,
        //     responseType: responseType,
        //     withCredentials: !!config.withCredentials,
        //     enableHttp2: true,
        //     enableQuic: true,
        //     enableCache: true,
        //     enableChunked: enableChunked,
        //     enableCookie: true,
        //     success, fail
        // })
        var requestTask = uni.request({
            url: buildURL(fullPath, config.params, config.paramsSerializer),
            data: requestData,
            method: config.method.toUpperCase(),
            header: requestHeaders.toJSON(),
            timeout: config.timeout < 1 ? undefined : config.timeout,
            dataType: responseType,
            responseType: responseType,
            withCredentials: !!config.withCredentials,
            enableHttp2: true,
            enableQuic: true,
            enableCache: true,
            enableChunked: enableChunked,
            enableCookie: true,
            success, fail
        })

        if (config.cancelToken || config.signal) {
            // Handle cancellation
            // eslint-disable-next-line func-names
            onCanceled = function (cancel) {
                if (!requestTask) {
                    return;
                }
                reject(!cancel || cancel.type ? new CanceledError(null, config, requestTask) : cancel);
                requestTask.abort();
                requestTask = null;
            };

            config.cancelToken && config.cancelToken.subscribe(onCanceled);
            if (config.signal) {
                config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
            }
        }
    });
};

// function uploadFile({ url, data, headers, timeout, success, fail }) {
//     var formData = {};
//     for (var pair of data.entries()) {
//         console.log(pair[0] + ", " + pair[1]);
//         if (formData[pair[0]]) {
//             if (Array.isArray(formData[pair[0]])) {
//                 formData[pair[0]].push(pair[1])
//             } else {
//                 formData[pair[0]] = [formData[pair[0]], pair[1]]
//             }
//         } else {
//             formData[pair[0]] = pair[1]
//         }
//     }
//     return uni.uploadFile({
//         url, headers, timeout, success, fail, formData
//     })
// }